package com.suredy.app.porject.export;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.CellType;
import jxl.Workbook;
import jxl.biff.DisplayFormat;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.format.VerticalAlignment;
import jxl.write.Blank;
import jxl.write.DateFormat;
import jxl.write.Label;
import jxl.write.Number;
import jxl.write.NumberFormat;
import jxl.write.NumberFormats;
import jxl.write.WritableCell;
import jxl.write.WritableCellFormat;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;

import com.suredy.core.ctrl.BaseCtrl;

public abstract class BaseExportorCtrl extends BaseCtrl {

	/** 每个视图最大的行数 */
	protected int MAX_LINE_OF_ONE_SHEET = 65536;

	/**
	 * 创建一个excel
	 * 
	 * @return
	 * @throws IOException
	 */
	protected WritableWorkbook createWorkbook(HttpServletRequest request, HttpServletResponse response, String fileName) throws IOException {
		if (response == null)
			throw new IllegalArgumentException("Invalid parameter HttpServletResponse[response].");

		this.resetContentType(request, response, fileName);

		return Workbook.createWorkbook(response.getOutputStream());
	}

	/**
	 * 创建一个excel页
	 * 
	 * @param book
	 * @param indexOfSheet
	 * @return
	 */
	protected WritableSheet createSheet(WritableWorkbook book, int indexOfSheet) {
		if (book == null)
			throw new IllegalArgumentException("Invalid parameter WritableWorkbook[book].");

		return book.createSheet("第" + (indexOfSheet + 1) + "页", indexOfSheet);
	}

	/**
	 * 创建单元格样式
	 * 
	 * @return
	 * @throws WriteException
	 */
	protected WritableCellFormat createCellFormat(CellType type, String dataFormat) throws WriteException {
		WritableCellFormat wcf = null;

		// 数字型
		if (type == CellType.NUMBER || type == CellType.NUMBER_FORMULA) {
			if (StringUtils.isBlank(dataFormat))
				dataFormat = "0.00";

			NumberFormat df = new NumberFormat(dataFormat);

			wcf = new WritableCellFormat(df);
		}

		// 日期类型
		if (type == CellType.DATE || type == CellType.DATE_FORMULA) {
			if (StringUtils.isBlank(dataFormat))
				dataFormat = "yyyy-MM-dd";

			DateFormat df = new DateFormat(dataFormat);

			wcf = new WritableCellFormat(df);
		}

		if (wcf == null)
			wcf = new WritableCellFormat();

		this.setCellStyle(wcf);

		return wcf;
	}

	/**
	 * 创建单元格样式
	 * 
	 * @return
	 * @throws WriteException
	 */
	protected WritableCellFormat createCellFormat(DisplayFormat df) throws WriteException {
		WritableCellFormat wcf = null;

		if (NumberFormats.PERCENT_FLOAT == df) {
			wcf = new WritableCellFormat(df);
		}

		if (wcf == null)
			wcf = new WritableCellFormat();

		this.setCellStyle(wcf);

		return wcf;
	}

	protected void writeCell(WritableSheet sheet, int row, int col, Integer data) throws RowsExceededException, WriteException {
		if (sheet == null)
			return;

		WritableCell cell = null;
		WritableCellFormat fmt = this.createCellFormat(null, null);

		if (data == null) {
			cell = new Blank(col, row, fmt);
		} else {
			cell = new Number(col, row, data, fmt);
		}

		sheet.addCell(cell);
	}

	protected void writeCell(WritableSheet sheet, int row, int col, String data) throws RowsExceededException, WriteException {
		if (sheet == null)
			return;

		WritableCell cell = null;
		WritableCellFormat fmt = this.createCellFormat(null, null);

		if (StringUtils.isBlank(data)) {
			cell = new Blank(col, row, fmt);
		} else {
			cell = new Label(col, row, data, fmt);
		}

		sheet.addCell(cell);
	}

	protected void writeCell(WritableSheet sheet, int row, int col, Double data) throws RowsExceededException, WriteException {
		if (sheet == null)
			return;

		WritableCell cell = null;
		WritableCellFormat fmt = this.createCellFormat(CellType.NUMBER, "0.00");

		if (data == null) {
			cell = new Blank(col, row, fmt);
		} else {
			cell = new Number(col, row, data, fmt);
		}

		sheet.addCell(cell);
	}

	protected void writeCellOfPercent(WritableSheet sheet, int row, int col, Double data) throws RowsExceededException, WriteException {
		if (sheet == null)
			return;

		WritableCell cell = null;
		WritableCellFormat fmt = this.createCellFormat(NumberFormats.PERCENT_FLOAT);

		if (data == null) {
			cell = new Blank(col, row, fmt);
		} else {
			cell = new Number(col, row, data, fmt);
		}

		sheet.addCell(cell);
	}

	/**
	 * 重置响应
	 * 
	 * @param response
	 * @param fileName
	 * @throws UnsupportedEncodingException
	 */
	protected void resetContentType(HttpServletRequest request, HttpServletResponse response, String fileName) {
		String userAgent = request.getHeader("User-Agent");

		try {
			if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
				fileName = URLEncoder.encode(fileName + ".xls", "UTF-8");
			} else {
				fileName = new String((fileName + ".xls").getBytes(Charsets.UTF_8), Charsets.ISO_8859_1);
			}
		} catch (UnsupportedEncodingException e) {
		}

		response.setContentType("application/vnd.ms-excel");
		response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
	}

	protected void setCellStyle(WritableCellFormat wcf) throws WriteException {
		if (wcf == null)
			return;

		wcf.setAlignment(jxl.format.Alignment.CENTRE);
		wcf.setVerticalAlignment(VerticalAlignment.CENTRE);
		wcf.setBorder(Border.ALL, BorderLineStyle.THIN);
		wcf.setBackground(Colour.WHITE);
		wcf.setWrap(Boolean.TRUE);
	}

	protected int getThisYear() {
		Calendar c = Calendar.getInstance();

		return c.get(Calendar.YEAR);
	}

	protected Date toDateStart(Date start) {
		if (start == null)
			return null;

		Calendar c = Calendar.getInstance();
		c.setTime(start);

		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);

		return c.getTime();

	}

	protected Date toDateEnd(Date end) {
		if (end == null)
			return null;

		Calendar c = Calendar.getInstance();
		c.setTime(end);

		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MILLISECOND, 999);

		return c.getTime();

	}

	protected Date getYearStart(int year) {
		Calendar c = Calendar.getInstance();

		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, Calendar.JANUARY);
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);

		return c.getTime();
	}

	protected Date getYearEnd(int year) {
		Calendar c = Calendar.getInstance();

		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, Calendar.DECEMBER);
		c.set(Calendar.DAY_OF_MONTH, 31);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MILLISECOND, 999);

		return c.getTime();
	}

	protected String datetimeFormat(Date date, String pattern) {
		if (date == null)
			return "";

		pattern = StringUtils.isBlank(pattern) ? "yyyy-MM-dd" : pattern;

		SimpleDateFormat sdf = new SimpleDateFormat(pattern);

		return sdf.format(date);
	}

}
